package com.wt.util;

import com.wt.mapper.IRowMapper;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * JDBC操作数据库
 * 1.加载数据库驱动(只需加载一次)
 * 2.连接数据库
 * 3.创建PreparedStatement对象
 * 4.执行SQL语句
 * 5.处理执行结果
 * 6.释放数据库资源（关闭数据库）
 */
public class DBHelper<E> {
    Connection conn = null;
    PreparedStatement pst = null;

    //1.加载数据库驱动(只需加载一次)
    static {
        try {
            Class.forName(getDataBaseDriver().getProperty("classDriver"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("数据库驱动加载失败");
        }

    }

    /**
     * 返回连接对象
     *
     * @return conn
     * @throws SQLException
     */
    public Connection getConnection() throws SQLException {
        if (conn == null || conn.isClosed()) {
            conn = DriverManager.getConnection(getDataBaseDriver().getProperty("url"),
                    getDataBaseDriver().getProperty("username"), getDataBaseDriver().getProperty("password"));
        }
        return conn;
    }

    /**
     * 为PreparedStatement添加参数
     *
     * @param objs 不定长数组，为SQL语句的？
     */
    private void setParameter(Object... objs) throws SQLException {
        //无参数时直接返回不需要添加参数
        if (objs == null || objs.length == 0) {
            return;
        }
        for (int i = 0; i < objs.length; i++) {
            pst.setObject(i + 1, objs[i]);
        }
    }

    /**
     * 添加，修改，删除操作
     *
     * @param sql  sql语句
     * @param objs 不定长参数（sql语句的？）
     * @return 影响行数
     */
    public int executeUpdate(String sql, Object... objs) throws SQLException {
        //预编译
        pst = conn.prepareStatement(sql);
        //设置参数把？赋值
        setParameter(objs);
        //执行并返回影响的行数
        return pst.executeUpdate();
    }

    /**
     * 模糊查询，需要单独处理单引号内的？问题
     * @param sql SQL语句
     * @param mapper 将每行数据转换为一个对象的接口，可借助其子类实现
     * @param objs 不定长参数
     * @return 对象集合
     */
    public List<E> executeLike(String sql,IRowMapper<E> mapper,Object... objs) throws SQLException {
        //预处理
        pst = conn.prepareStatement(sql);
        //无参数时直接返回不需要添加参数
        if (objs != null) {
            for (int i = 0; i < objs.length; i++) {
                pst.setObject(i + 1, "%"+objs[i]+"%");
            }
        }
        ResultSet rs = pst.executeQuery();
        List<E> list = new ArrayList<>();
        while (rs.next()) {
            E e = mapper.rowMapper(rs);
            list.add(e);
        }
        return list;
    }

    /**
     * 查询结果
     *
     * @param sql    SQL语句
     * @param objs   不定长参数
     * @param mapper IRowMapper的实现子类
     * @return 结果集
     */
    public List<E> executeQuery(String sql, IRowMapper<E> mapper, Object... objs) throws SQLException {
        //预编译
        pst = conn.prepareStatement(sql);
        setParameter(objs);
        ResultSet rs = pst.executeQuery();
        List<E> list = new ArrayList<>();
        while (rs.next()) {
            E e = mapper.rowMapper(rs);
            list.add(e);
        }
        return list;
    }

    /**
     * 释放数据库资源
     */
    public void closeConnection() throws SQLException {
        if (pst != null) {
            pst.close();
        }
        if (conn != null) {
            conn.close();
        }
    }

    /**
     * 读取数据库配置文件
     *
     * @return Properties
     */
    private static Properties getDataBaseDriver() {
        //建立输入流
        InputStream is = DBHelper.class.getResourceAsStream("/database.properties");

        Properties dbproperties = new Properties();

        try {
            //把文件的内容读到集合中
            dbproperties.load(is);

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return dbproperties;
    }
}
